<script setup lang="ts">
import { nextTick, onMounted, ref } from 'vue'
import ApprovalStatusTag from './ApprovalStatusTag.vue'

// 定义信息项接口
export interface InfoItem {
  label: string
  value: any
  key?: string
  forceMultiline?: boolean // 强制多行显示（适用于备注等字段）
  slot?: string // 自定义插槽名称
  type?: 'default' | 'currency' | 'date' | 'datetime' | 'time' | 'percentage' | 'status' | 'url' | 'filesize' | 'approval' // 字段类型
}

// 定义组件Props
const props = withDefaults(defineProps<{
  title: string
  infoList: InfoItem[]
  showDivider?: boolean
}>(), {
  showDivider: true,
})

// 存储每个value元素是否超出一行的状态
const valueOverflowMap = ref<Record<number, boolean>>({})

// 格式化键值对显示的辅助函数
function formatValue(value: any, type?: InfoItem['type']): string {
  if (value === null || value === undefined || value === '') {
    return '-'
  }

  // 根据类型格式化显示
  switch (type) {
    case 'currency':
      return formatCurrency(value)
    case 'date':
      return formatDate(value)
    case 'datetime':
      return formatDateTime(value)
    case 'time':
      return formatTime(value)
    case 'percentage':
      return formatPercentage(value)
    case 'status':
      return formatStatus(value)
    case 'url':
      return formatUrl(value)
    case 'filesize':
      return formatFileSize(value)
    default:
      if (typeof value === 'object') {
        return JSON.stringify(value)
      }
      return String(value)
  }
}

// 格式化金额
function formatCurrency(value: any): string {
  const num = Number.parseFloat(value)
  if (Number.isNaN(num))
    return String(value)

  // 确保金额格式化为千分位和两位小数
  // 使用字符串操作实现，确保在所有平台都能正常工作
  const formattedNum = num.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
  return `￥${formattedNum}`
}

// 格式化日期
function formatDate(value: any): string {
  if (!value)
    return '-'
  const date = new Date(value)
  if (Number.isNaN(date.getTime()))
    return String(value)

  // 使用 yyyy-MM-dd 格式
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')

  return `${year}-${month}-${day}`
}

// 格式化日期时间
function formatDateTime(value: any): string {
  if (!value)
    return '-'
  const date = new Date(value)
  if (Number.isNaN(date.getTime()))
    return String(value)

  // 使用 yyyy-MM-dd HH:mm:ss 格式
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  const hour = String(date.getHours()).padStart(2, '0')
  const minute = String(date.getMinutes()).padStart(2, '0')
  const second = String(date.getSeconds()).padStart(2, '0')

  return `${year}-${month}-${day} ${hour}:${minute}:${second}`
}

// 格式化时间
function formatTime(value: any): string {
  if (!value)
    return '-'
  const date = new Date(value)
  if (Number.isNaN(date.getTime()))
    return String(value)

  // 获取各个时间组件
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  const hour = String(date.getHours()).padStart(2, '0')
  const minute = String(date.getMinutes()).padStart(2, '0')
  const second = String(date.getSeconds()).padStart(2, '0')

  // 返回 "YYYY-MM-DD HH:mm:ss" 格式
  return `${year}-${month}-${day} ${hour}:${minute}:${second}`
}

// 格式化百分比
function formatPercentage(value: any): string {
  const num = Number.parseFloat(value)
  if (Number.isNaN(num))
    return String(value)
  return `${num.toFixed(2)}%`
}

// 格式化状态
function formatStatus(value: any): string {
  const statusMap: Record<string, { text: string, color?: string }> = {
    pending: { text: '待处理', color: '#ff9500' },
    approved: { text: '已通过', color: '#52c41a' },
    rejected: { text: '已拒绝', color: '#ff4d4f' },
    processing: { text: '处理中', color: '#1890ff' },
    completed: { text: '已完成', color: '#52c41a' },
    cancelled: { text: '已取消', color: '#8c8c8c' },
    active: { text: '启用', color: '#52c41a' },
    inactive: { text: '禁用', color: '#ff4d4f' },
    success: { text: '成功', color: '#52c41a' },
    error: { text: '失败', color: '#ff4d4f' },
    warning: { text: '警告', color: '#faad14' },
  }
  const status = statusMap[value]
  return status ? status.text : String(value)
}

// 格式化URL
function formatUrl(value: any): string {
  if (!value)
    return '-'
  try {
    const url = new URL(value)
    return url.hostname + (url.pathname !== '/' ? url.pathname : '') + (url.search || '')
  }
  catch {
    return String(value)
  }
}

// 格式化文件大小
function formatFileSize(value: any): string {
  const bytes = Number.parseInt(value)
  if (Number.isNaN(bytes))
    return String(value)

  const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
  if (bytes === 0)
    return '0 B'

  const i = Math.floor(Math.log(bytes) / Math.log(1024))
  const size = (bytes / 1024 ** i).toFixed(1)

  return `${size} ${sizes[i]}`
}

// 检查元素是否超出一行（使用uni-app兼容的方式）
function checkOverflow(index: number) {
  nextTick(() => {
    // #ifdef H5
    const valueElement = document.querySelector(`.info-value[data-index="${index}"]`) as HTMLElement
    if (valueElement) {
      const isOverflow = valueElement.scrollWidth > valueElement.clientWidth
      valueOverflowMap[index] = isOverflow
    }
    // #endif

    // #ifndef H5
    // 非H5环境（小程序/APP等）通过判断文本长度来模拟溢出检测
    const currentItem = props.infoList[index]
    if (currentItem && currentItem.value) {
      const textLength = String(currentItem.value).length
      const isOverflow = textLength > 20 // 假设超过20个字符认为溢出
      valueOverflowMap[index] = isOverflow
    }
    // #endif
  })
}

// 复制文本到剪贴板
async function copyToClipboard(text: string, index: number) {
  try {
    // 格式化文本，确保不是 null 或 undefined
    const formattedText = formatValue(text)
    if (formattedText === '-')
      return

    // #ifdef H5
    await navigator.clipboard.writeText(formattedText)
    // #endif

    // #ifndef H5
    // 小程序和APP使用uni-app API
    await uni.setClipboardData({
      data: formattedText,
    })
    // #endif

    // 显示复制成功提示
    uni.showToast({
      title: '复制成功',
      icon: 'success',
      duration: 1500,
    })
  }
  catch (error) {
    console.error('复制失败:', error)
    uni.showToast({
      title: '复制失败',
      icon: 'error',
      duration: 1500,
    })
  }
}

// 组件挂载后检查所有元素
onMounted(() => {
  nextTick(() => {
    props.infoList.forEach((_, index) => {
      checkOverflow(index)
    })
  })
})
</script>

<template>
  <view class="detail-card">
    <view class="card-header">
      <view class="card-title">
        {{ title }}
      </view>
    </view>
    <view class="card-content">
      <view
        v-for="(item, index) in infoList"
        :key="item.key || index"
        class="info-item" :class="[(valueOverflowMap[index] || item.forceMultiline) ? 'info-item-vertical' : 'info-item-horizontal']"
      >
        <view class="info-label">
          {{ item.label }}
        </view>
        <view
          v-if="item.slot"
          class="info-value info-value-slot overflow-hidden"
        >
          <!-- 如果有自定义插槽，使用插槽；否则使用默认显示 -->
          <slot :name="item.slot" :item="item" :index="index" :value="item.value" />
        </view>
        <view
          v-else
          class="info-value"
          :class="(valueOverflowMap[index] || item.forceMultiline) ? 'info-value-multiline' : 'info-value-single'"
          :data-index="index"
          @dblclick="copyToClipboard(item.value, index)"
        >
          <span v-if="item.type === 'currency'" class="currency-amount">{{ formatValue(item.value, item.type) }}</span>
          <span v-else-if="item.type === 'approval'" class="approval-status-tag">
            <approval-status-tag :value="item.value" type="color" />
          </span>
          <span v-else>{{ formatValue(item.value, item.type) }}</span>
        </view>
      </view>
    </view>
  </view>
</template>

<style scoped>
.detail-card {
  background-color: #fff;
  border-radius: 12rpx;
  margin-bottom: 20rpx;
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
}

.card-header {
  padding: 20rpx 30rpx;
  border-bottom: 1rpx solid #f0f0f0;
}

.card-title {
  font-size: 32rpx;
  font-weight: 600;
  color: #333;
}

.card-content {
  padding: 20rpx 30rpx;
}

.info-item {
  padding: 16rpx 0;
  border-bottom: 1rpx solid #f5f5f5;
}

.info-item:last-child {
  border-bottom: none;
}

.info-item-horizontal {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
}

.info-item-vertical {
  display: flex;
  flex-direction: column;
  gap: 16rpx;
}

.info-label {
  font-size: 28rpx;
  color: #666;
  line-height: 1.4;
  font-weight: 500;
}

.info-item-horizontal .info-label {
  min-width: 160rpx;
}

.info-value {
  font-size: 28rpx;
  color: #333;
  word-break: break-all;
  line-height: 1.4;
}

.info-value-slot {
  position: relative;
  min-height: 60rpx;
  display: flex;
  align-items: flex-start;
}

/* 单行显示样式（无背景） */
.info-value-single {
  flex: 1;
  margin-left: 20rpx;
  text-align: right;
}

/* 多行显示样式（有背景） */
.info-value-multiline {
  background-color: #f8f9fa;
  padding: 16rpx;
  border-radius: 8rpx;
  min-height: 60rpx;
  display: flex;
  align-items: flex-start;
  border: 1rpx solid #e9ecef;
}

/* 金额样式 - 红色字体和加粗 */
.currency-amount {
  color: #e55e35;
  font-weight: 600;
  font-size: 32rpx;
}
</style>
